package com.jh.paymentchannel.controller;


import cn.jh.common.exception.ServiceException;
import cn.jh.common.pay.client.FreeQuickResponse;
import cn.jh.common.pay.jdpush.OrderStatus;
import cn.jh.common.utils.ChannelType;
import cn.jh.common.utils.CommonConstants;
import cn.jh.common.utils.CommonsUtil;
import cn.jh.common.utils.TokenUtil;
import com.jh.paymentchannel.pojo.freeQuick.FreeQuickOrder;
import com.jh.paymentchannel.pojo.freeQuick.FreeQuickWithdraw;
import com.jh.paymentchannel.pojo.freeQuick.FreeQuickWithdrawTemp;
import com.jh.paymentchannel.repository.freeQuick.FreeQuickOrderRepository;
import com.jh.paymentchannel.repository.freeQuick.FreeQuickWithdrawTempRepository;
import com.jh.paymentchannel.service.freeQuick.FreeQuickPayService;
import com.jh.paymentchannel.util.Util;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.net.URI;
import java.util.*;

import static org.springframework.util.StringUtils.hasText;

/**
 * 畅捷快捷支付
 * @author lichengying
 */
@Controller
@EnableScheduling
@EnableAutoConfiguration
public class FreeQuickPayController {

    @Autowired
    private Util util;
    private final FreeQuickPayService freeQuickPayService;
    private final FreeQuickOrderRepository freeQuickOrderRepository;
    private final FreeQuickWithdrawTempRepository freeQuickWithdrawTempRepository;

    @Autowired
    public FreeQuickPayController(FreeQuickOrderRepository freeQuickOrderRepository,
                                  FreeQuickWithdrawTempRepository freeQuickWithdrawTempRepository,
                                  FreeQuickPayService freeQuickPayService) {
        this.freeQuickPayService = freeQuickPayService;
        this.freeQuickOrderRepository = freeQuickOrderRepository;
        this.freeQuickWithdrawTempRepository = freeQuickWithdrawTempRepository;
    }

    @Value("${schedule-task.on-off}")
    private String scheduleTaskOnOff;

    private static final Log log = LogFactory.getLog(FreeQuickPayController.class);

    /**
     * 畅捷交易
     * @return
     */
    @RequestMapping(method= RequestMethod.POST,value="/v1.0/paymentchannel/freeQuick/consumption/{token}")
    public @ResponseBody Object consumption(@PathVariable("token") String token, FreeQuickOrder freeQuickOrder){
        try {
            Map para = freeQuickPayService.payment(freeQuickOrder);
            String code = (String)para.getOrDefault("code","1");
            String msg = (String)para.getOrDefault("msg","1");
            if(code.equals("0")){
                return CommonsUtil.returnError(msg);
            }
            return CommonsUtil.returnSuccess("");
        }catch (Exception e){
            log.error("FreeQuickPayController.consumption,畅捷交易异常======" + e.getMessage());
            return CommonsUtil.returnError("交易失败！");
        }
    }


    /**
     * 畅捷提现查询
     * @param entity
     * @return
     */
    @RequestMapping(method= RequestMethod.GET,value="/v1.0/paymentchannel/freeQuick/querywithdraw")
    public @ResponseBody Object querywithdraw(FreeQuickWithdraw entity){
        try {
            Map map = freeQuickPayService.querywithdraw(entity);
            if(map.isEmpty()){
                return CommonsUtil.returnError("查询失败！");
            }
            return CommonsUtil.returnSuccess("还款成功");
        }catch (Exception e){
            log.error("FreeQuickPayController.querywithdraw,畅捷还款接口异常======" + e.getMessage());
            return CommonsUtil.returnError("还款失败！" + e.getMessage());
        }
    }


    /**
     * 在线收款
     * @param freeQuickOrder
     * @return
     */
    @RequestMapping(method= RequestMethod.POST,value="/v1.0/paymentchannel/freeQuick/receivables/{token}")
    public @ResponseBody Object onlineReceivables(HttpServletRequest request,@PathVariable("token") String token,  FreeQuickOrder freeQuickOrder){
        long userId = 0;
        try {
            userId = TokenUtil.getUserId(token);
            if (freeQuickOrder.getChannelProductCode().equals("5")) {
                String ip = request.getRemoteAddr();
                freeQuickOrder.setClientIp(ip);
            }
            freeQuickOrder.setInAmount(new BigDecimal(freeQuickOrder.getAmount()));
            //查询银行卡
            Map map = verifyBankInfo(freeQuickOrder.getBankCardNo(),userId,"1",freeQuickOrder.getChannelProductCode(),"1");
            String code = (String) map.getOrDefault("resp_code","0");
            String msg = (String) map.getOrDefault("resp_message","0");
            if(!code.equals(CommonConstants.SUCCESS)){
                if(!msg.equals("0")){
                    if(msg.equalsIgnoreCase(CommonConstants.PENDING)){
                        String cardType = (String) map.getOrDefault("cardType","0");
                        String cardId = (String) map.getOrDefault("cardNo","0");
                        map.put("cardType",cardType);
                        map.put(CommonConstants.RESP_CODE,CommonConstants.ERROR_FREE_QUICK_BINK);
                        if(cardType.equals("1")){
                            map.put(CommonConstants.RESP_MESSAGE,"请输入消费银行卡短信验证");
                        }else if(cardType.equals("2")){
                            map.put(CommonConstants.RESP_MESSAGE,"请输入到账银行卡短信验证");
                        }
                        map.put("cardId",cardId);
                        return map;
                    }else if(msg.equalsIgnoreCase(CommonConstants.FAIL)){
                        return CommonsUtil.returnError(CommonConstants.ERROR_FREE_QUICK_BINK_ERROR,CommonConstants.ERROR_FREE_QUICK_BINK_ERROR_MSG);
                    }else{
                        boolean fle = CommonsUtil.verifyError(code);
                        if(!fle){
                            return CommonsUtil.returnError(code,msg);
                        }
                    }
                }
                boolean fle = CommonsUtil.verifyError(code);
                if(!fle){
                    return CommonsUtil.returnError(code,CommonsUtil.freeQuickError(code));
                }
            }

            Map result = (Map) map.getOrDefault("result","0");
            //查询费率
            Map pram = (Map) result.get("channelRate");
            String merchantNo = (String) result.getOrDefault("merchantNo","0");
            freeQuickOrder.setMerchantNo(merchantNo);

            String amount = freeQuickOrder.getAmount();
            BigDecimal amounts = new BigDecimal(amount);

            //查询费率
            if (pram.isEmpty()) {
                return CommonsUtil.returnError("费率不能为空");
            }
            Double rate = (Double) pram.getOrDefault("rate", "0");//交易单笔交易手续费
            int extraFee = MapUtils.getInteger(pram,"extraFee");//交易用户费率
            freeQuickOrder.setRate(new BigDecimal(rate));
            freeQuickOrder.setChannelTag(ChannelType.of(Integer.valueOf(freeQuickOrder.getChannelProductCode())).getValue());
            //计算在线交易+提现费率和手续费

            freeQuickOrder.setPayType("1");

            String productName = CommonsUtil.queryProductName();
            if (freeQuickOrder.getChannelProductCode().equals("1")) {
                freeQuickOrder.setProductName(productName);
                freeQuickOrder.setProductDesc(productName);
            } else {
                freeQuickOrder.setProductName(productName);
                freeQuickOrder.setProductDesc(productName);
            }
            freeQuickOrder.setUserId(String.valueOf(userId));
            //交易
            Map prams = freeQuickPayService.payment(freeQuickOrder);
            code = (String) prams.getOrDefault("code", "0");
            String bizCode = (String) prams.getOrDefault("bizCode", "0");
            String requestNo = (String) prams.getOrDefault("requestNo", "0");
            msg = (String) prams.getOrDefault("msg", "0");
            if (!code.equals(CommonConstants.FREE_SUCCESS)) {
                return CommonsUtil.returnError(CommonsUtil.freeQuickError(bizCode));
            } else {
                if (!bizCode.equals("1")) {
                    return CommonsUtil.returnError(bizCode, CommonsUtil.freeQuickError(bizCode));
                }
            }
            //提现
            FreeQuickWithdrawTemp entity = new FreeQuickWithdrawTemp();
            entity.setMerchantNo(merchantNo);
            entity.setRequestNo(requestNo);
            entity.setPayStatus("0");
            entity.setInAmount(new BigDecimal(freeQuickOrder.getAmount()));
            entity.setUserId(String.valueOf(userId));
            entity.setPayType("1");
            BigDecimal avg = avgBigDecimal(amounts, rate, extraFee);
            entity.setAmount(String.valueOf(avg));//提现金额
            entity.setChannelId(freeQuickOrder.getChannelProductCode());
            //保存提现临时任务
            freeQuickPayService.saveWithdraw(entity);
            return CommonsUtil.returnSuccess("刷卡成功！");
        }catch (Exception e){
            log.error("FreeQuickPayController.onlineReceivables,畅捷在线收款接口异常======" + e.getMessage());
            e.printStackTrace();
            return CommonsUtil.returnError("刷卡失败！" );
        }
    }


    /**
     * 5分钟查询提现状态
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    public void timedTaskWithdraws() {
        try {
            freeQuickPayService.getAllInProcessPay();
        }catch (Exception e){
            log.error("FreeQuickPayController.timedTaskFreeQuickPayment,每30秒查询一次通道交易状态异常====" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 每3分钟查询一次交易状态成功进行通道提现
     */
    @Scheduled(cron = "0 0/3 * * * ?")
    public void timedTaskWithdraw() {
        try {
            //待提现
            freeQuickPayService.queryWithdrawTemp();
        }catch (Exception e){
            log.error("FreeQuickPayController.timedTaskWithdraw,交易状态成功进行通道提现异常=====" + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 执行代还计划
     * @param withdraw
     * @return
     */
    @RequestMapping(method= RequestMethod.POST,value="/v1.0/paymentchannel/freeQuick/repaymentTask")
    public @ResponseBody Object repaymentTask(FreeQuickWithdraw withdraw){
        try {
            Map map = verifyBankInfo(withdraw.getBankAccountNo(),Long.valueOf(withdraw.getUserId()),"1",withdraw.getChannelCode(),"1");
            Map result = (Map) map.getOrDefault("result","0");
            String merchantNo = (String) result.getOrDefault("merchantNo","0");
            withdraw.setMerchantNo(merchantNo);
            Map para = freeQuickPayService.withdraw(withdraw);
            String code = (String)para.getOrDefault("code","1");
            String msg = (String)para.getOrDefault("msg","1");
            if(code.equals("0")){
                return CommonsUtil.returnError(msg);
            }
            return CommonsUtil.returnSuccess("");
        }catch (Exception e){
            log.error("FreeQuickPayController.repaymentTask，执行还款计划异常=====" + e.getMessage());
            return CommonsUtil.returnError("执行还款计划失败！");
        }
    }

    /**
     * 执行交易计划
     * @param freeQuickOrder
     * @return
     */
    @RequestMapping(method= RequestMethod.POST,value="/v1.0/paymentchannel/freeQuick/consumptionTask")
    public @ResponseBody Object consumptionTask(FreeQuickOrder freeQuickOrder,String orderNo){
        try {
            freeQuickOrder.setRequestNo(orderNo);
            String productName = CommonsUtil.queryProductName();
            freeQuickOrder.setProductName(productName);
            freeQuickOrder.setProductDesc(productName);
            Map<String,Object> map = getMerchantNo(freeQuickOrder.getUserId(),freeQuickOrder.getChannelProductCode());
            if (map != null) {
                Map<String,String> result = MapUtils.getMap(map,"result");
                String merchantNo = result.getOrDefault("merchantNo","0");
                if (merchantNo.equals("0")) {
                    return CommonsUtil.returnError("用户信息不完整");
                }
                freeQuickOrder.setMerchantNo(merchantNo);
                Map para = freeQuickPayService.payment(freeQuickOrder);
                para.put("code" , para.getOrDefault("code","1"));
                para.put("msg" , para.getOrDefault("msg","1"));
                para.put(CommonConstants.RESP_CODE, para.getOrDefault("bizCode","1"));
                return para;
            }
            return CommonsUtil.returnError("用户信息不完整");
        }catch (Exception e){
            log.error("FreeQuickPayController.consumptionTask，执行交易计划异常======" + e.getMessage());
            return CommonsUtil.returnError("执行交易计划失败！");
        }

    }

    private Map<String,Object> getMerchantNo(String userId,String channelProductCode) {
        /* 1、获取请求模块地址 */
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/app/query/RegisterMerchant";

        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("userId", userId);
        requestEntity.add("channelProductCode",channelProductCode);
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        Map<String,Object> map = JSONObject.fromObject(result);
        return map;
    }

    /**
     * 查询use模块银行卡信息和汇率信息
     * @param cardNo
     *
     */
    public Map verifyBankInfo(String cardNo,long userId,String idDef,String channelId,String payType){
        URI uri = util.getServiceUrl("user", "error url request");
        String url = uri.toString() + "/v1.0/user/register/bankInfo";
        LinkedMultiValueMap<String,String> requestEntity = new LinkedMultiValueMap<String,String>();
        requestEntity.add("cardNo", cardNo);
        requestEntity.add("userId", userId + "");
        requestEntity.add("idDef", idDef);
        requestEntity.add("channelId", channelId);
        requestEntity.add("channelType", channelId);
        requestEntity.add("payType", payType);
        RestTemplate restTemplate = new RestTemplate();
        String resultString = restTemplate.postForObject(url, requestEntity, String.class);
        Map map = JSONObject.fromObject(resultString);
        return map;
    }

    /**
     * 在线收款费率计算
     * @param amounts 计算费率金额
     * @param rate 提现费率
     * @param extraFee 提现手续费
     * @return
     */
    public BigDecimal avgBigDecimal(BigDecimal amounts , Double rate,
                                    double extraFee){
        BigDecimal rates = new BigDecimal(rate);//
        BigDecimal extraFees = new BigDecimal(extraFee);
        BigDecimal sum = amounts.multiply(rates);
        BigDecimal fee = sum.add(extraFees);
        BigDecimal avg = fee.setScale(2,BigDecimal.ROUND_UP);
        amounts = amounts.subtract(avg);
        return amounts;
    }

    /**
     * 分页查询畅捷交易记录表信息
     * @param userId
     * @param payType 交易入口 1:在线收款，2：代还
     * @param page
     * @param size
     * @param direction
     * @param sortProperty
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuick/findPassagewayOrderPage")
    public @ResponseBody Object findPassagewayOrderPage (
            @RequestParam(value = "userId", defaultValue = "", required = false) String userId,
            @RequestParam(value = "payType", defaultValue = "", required = false) String payType,
            @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
            @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime,
            @RequestParam(value = "requestNo", defaultValue = "", required = false) String requestNo,//请求流水号
            @RequestParam(value = "merchantNo", defaultValue = "", required = false) String merchantNo,//商户订单号
            @RequestParam(value = "channelProductCode", defaultValue = "", required = false) String channelProductCode,//渠道产品编号
            @RequestParam(value = "bankCardNo", defaultValue = "", required = false) String bankCardNo,//银行卡号
            @RequestParam(value = "productName", defaultValue = "", required = false) String productName,//产品名称
            @RequestParam(value = "channelType", defaultValue = "", required = false) String channelType,//商户类型
            @RequestParam(value = "payStatus", defaultValue = "", required = false) String payStatus,//交易状态0:待交易,1：成功，2：失败，3：异常,4：交易中；
            @RequestParam(value = "page", defaultValue = "0", required = false) int page,
            @RequestParam(value = "size", defaultValue = "20", required = false) int size,
            @RequestParam(value = "order", defaultValue = "DESC", required = false) Sort.Direction direction,
            @RequestParam(value = "sort", defaultValue = "createTime", required = false) String sortProperty) {
        Pageable pageable = new PageRequest(page, size, new Sort(direction, sortProperty));
        Page<FreeQuickOrder> passagewayOrderPage = freeQuickPayService.findPassagewayOrderPage(startTime, endTime, requestNo, merchantNo, channelProductCode,
                bankCardNo, productName, channelType, payStatus, userId, payType, pageable);
        List<FreeQuickOrder> content = passagewayOrderPage.getContent();
        for (FreeQuickOrder free : content) {
            free.setChannelTag(free.ofChannelTag());
            free.emptyToString();
        }
        return CommonsUtil.returnSuccess("查询成功", passagewayOrderPage);
    }

    /**
     * 分页查询畅捷代还/提现记录
     * @param userId
     * @param payType
     * @param page
     * @param size
     * @param direction
     * @param sortProperty
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuick/findFreeQuickWithdrawPage")
    public @ResponseBody Object findFreeQuickWithdrawPage (
            @RequestParam(value = "userId", defaultValue = "", required = false) String userId,
            @RequestParam(value = "requestNo", defaultValue = "", required = false) String requestNo,//请求流水号
            @RequestParam(value = "merchantNo", defaultValue = "", required = false) String merchantNo,//商户编号
            @RequestParam(value = "channelCode", defaultValue = "", required = false) String channelCode,//渠道编号
            @RequestParam(value = "bankAccountNo", defaultValue = "", required = false) String bankAccountNo,//银行账号
            @RequestParam(value = "bankAccountName", defaultValue = "", required = false) String bankAccountName,//银行账户名
            @RequestParam(value = "bankAccountType", defaultValue = "", required = false) String bankAccountType,//银行账户类型
            @RequestParam(value = "bankName", defaultValue = "", required = false) String bankName,//银行名称
            @RequestParam(value = "bankSubName", defaultValue = "", required = false) String bankSubName,//支行名称
            @RequestParam(value = "bankProvince", defaultValue = "", required = false) String bankProvince,//银行所属省
            @RequestParam(value = "bankCity", defaultValue = "", required = false) String bankCity,//银行所属市
            @RequestParam(value = "withdrawRequestNo", defaultValue = "", required = false) String withdrawRequestNo,//提现流水号
            @RequestParam(value = "payType", defaultValue = "", required = false) String payType,//交易入口，1:在线收款，2：代还，3：余额提现
            @RequestParam(value = "channelType", defaultValue = "", required = false) String channelType,//1：商旅，2：新无卡101，3：新无卡102
            @RequestParam(value = "payStatus", defaultValue = "", required = false) String payStatus,//交易状态0:待提现,1：成功，2：失败，3：异常,4：提现中；
            @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
            @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime,
            @RequestParam(value = "page", defaultValue = "0", required = false) int page,
            @RequestParam(value = "size", defaultValue = "20", required = false) int size,
            @RequestParam(value = "order", defaultValue = "DESC", required = false) Sort.Direction direction,
            @RequestParam(value = "sort", defaultValue = "createTime", required = false) String sortProperty) {
        Pageable pageable = new PageRequest(page, size, new Sort(direction, sortProperty));
        Page<FreeQuickWithdraw> freeQuickWithdrawPage = freeQuickPayService.findFreeQuickWithdrawPage(userId, requestNo, merchantNo, channelCode, bankAccountNo,
                bankAccountName, bankAccountType, bankName, bankSubName, bankProvince, bankCity, withdrawRequestNo, payType, channelType, payStatus,startTime,
                endTime, pageable);
        List<FreeQuickWithdraw> content = freeQuickWithdrawPage.getContent();
        for (FreeQuickWithdraw free : content) {
            free.setChannelTag(free.ofChannelTag());
            FreeQuickWithdraw.emptyToString(free);
        }
        return CommonsUtil.returnSuccess("查询成功", freeQuickWithdrawPage);
    }

    /**
     * 余额提现
     * @param token
     * @param balance 提现之前余额
     * @param amount 提现金额
     * @param rate 提现费率
     * @param extraFee 操作手续费
     * @param bankCard 银行卡
     * @param channelType 通道类型
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/BalanceWithdraw/{token}")
    public @ResponseBody Object BalanceWithdraw(@PathVariable("token") String token,
                                         @RequestParam("balance") BigDecimal balance,
                                         @RequestParam("amount") BigDecimal amount,
                                         @RequestParam("rate") BigDecimal rate,
                                         @RequestParam("extraFee") BigDecimal extraFee,
                                         @RequestParam("bankCard") String bankCard,
                                         @RequestParam("channelType") String channelType) {
        long userId = 0l;
        FreeQuickWithdraw entity = new FreeQuickWithdraw();
        Map<String, Object> res = new HashMap<>();
        try {
            userId = TokenUtil.getUserId(token);
        } catch (Exception e) {
            return CommonsUtil.returnError("token无效");
        }

        log.info("余额提现/v1.0/paymentchannel/freeQuickPay/withdraw/{token} userId = " + userId);

        try {
            /* 1、获取用户信息 */
            URI uri = util.getServiceUrl("user", "error url request!");
            String url = uri.toString() + "/v1.0/user/find/by/userid";

            MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
            requestEntity.add("userId", String.valueOf(userId));

            RestTemplate restTemplate = new RestTemplate();
            String result = restTemplate.postForObject(url, requestEntity, String.class);

            log.info("余额提现时查询用户信息/v1.0/user/find/by/userid result = " + result);

            JSONObject resultJ = JSONObject.fromObject(result);
            result = resultJ.get("result").toString();
            if (StringUtils.isEmpty(result)) {
                return CommonsUtil.returnError("获取用户信息失败！");
            }
            JSONObject userJ = JSONObject.fromObject(result);
            String password = "";
            if (userJ.containsKey("password")) {
                password = userJ.get("password").toString();
            }

            /* 2、银行卡校验，并判断是否注册通道 */
            if (StringUtils.isEmpty(bankCard)) {
                return CommonsUtil.returnError("银行卡不能为空！");
            }
            Map<String, Object> checkResult = verifyBankInfo(bankCard, userId, "1", "2","1");

            log.info("验证银行卡结果checkResult = " + checkResult);

            result = checkResult.get("result").toString();
            resultJ = JSONObject.fromObject(result);
            if (StringUtils.isEmpty(resultJ.toString())) {
                return CommonsUtil.returnError("银行卡有误");
            }

            String code = (String) checkResult.getOrDefault("resp_code","0");
            String msg = (String) checkResult.getOrDefault("resp_message","0");
            if(!code.equals(CommonConstants.SUCCESS)){
                if(org.apache.commons.lang.StringUtils.isNotBlank(msg)){
                    if(msg.equalsIgnoreCase(CommonConstants.UNPAY)){
                        return CommonsUtil.returnError(CommonConstants.ERROR_FREE_QUICK_BINK,CommonConstants.ERROR_FREE_QUICK_BINK_MSG);
                    }else if(msg.equalsIgnoreCase(CommonConstants.UNKNOW)){
                        return CommonsUtil.returnError(CommonConstants.ERROR_FREE_QUICK_BINK_ERROR,CommonConstants.ERROR_FREE_QUICK_BINK_ERROR_MSG);
                    }else{
                        return CommonsUtil.returnError(CommonConstants.ERROR_FREE_QUICK_LOGIN,CommonConstants.ERROR_FREE_QUICK_LOGIN_MSG);
                    }
                }
            }

            /* 3、提现金额校验 */
            if (amount.compareTo(new BigDecimal("100.00")) == -1) {
                return CommonsUtil.returnError("单笔提现金额不能低于100.00元！");
            }
            if (amount.compareTo(new BigDecimal("20000")) == 1) {
                return CommonsUtil.returnError("单笔提现金额不能高于20000.00元！");
            }
            if (amount.compareTo(balance) == 1) {
                return CommonsUtil.returnError("余额不足，无法提现！");
            }

            Map<String, Object> defaultChannel = queryChannel(userId, "", "");
            //defaultChannel.remove("channelParams");
            //defaultChannel.remove("autoclearing");
            res.put("defaultChannel", defaultChannel);
            String channelNo = defaultChannel.getOrDefault("channelNo", "2").toString();

            /* 4、查询通道商户编号和商户请求编号 */

            /* 5、封装-畅捷代还/提现记录表 */
            entity.setUserId(String.valueOf(userId));
            entity.setBankProvince(resultJ.getOrDefault("province", "").toString());
            entity.setBankCity(resultJ.getOrDefault("city", "").toString());
            entity.setBankArea(resultJ.getOrDefault("city", "").toString());
            entity.setBankAccountNo(bankCard);
            entity.setBankAccountName(resultJ.getOrDefault("bankName", "").toString());
            entity.setBankName(resultJ.getOrDefault("bankName", "").toString());
            entity.setBankSubName(resultJ.getOrDefault("bankBranchName", "").toString());
            entity.setBankChannelNo(resultJ.getOrDefault("lineNo", "").toString());
            entity.setBankCode(resultJ.getOrDefault("bankBranchName", "").toString());
            entity.setBankAbbr(resultJ.getOrDefault("bankBranchName", "").toString());
            entity.setWalletType(CommonConstants.WALLET_TYPE_SAME_DAY);
            entity.setAmount(amount.toString());
            entity.setPayType("3");//余额提现
            entity.setChannelType(channelType);//通道类型
            entity.setChannelCode(channelNo);
            entity.setInAmount(amount);

            Map<String, Object> stringObjectMap = freeQuickPayService.balanceWithdraw(entity, balance, bankCard, rate, extraFee);
            Object resp_code = stringObjectMap.get("resp_code");
            if (CommonConstants.FALIED.equals(resp_code)) {
                return CommonsUtil.returnError("提现失败！");
            }
            Object userAccount =  stringObjectMap.get("result");
            res.put("userAccount", userAccount);

            return CommonsUtil.returnSuccess("提现成功", res);
        } catch (Exception e) {
            return CommonsUtil.returnError("提现失败！");
        }
    }

    /**
     * 校验用户银行卡信息
     * @param userId
     * @param bankcard
     * @return
     */
    private Map<String, Object> checkBankCard(long userId, String bankcard) {
        Map<String, Object> resMap = new HashMap<>();
        RestTemplate restTemplate = new RestTemplate();
        URI uri = util.getServiceUrl("user", "error url request");
        String url = uri.toString() + "/v1.0/user/bank/verify/isuseable";
        LinkedMultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<String, String>();
        requestEntity.add("userId", String.valueOf(userId));
        requestEntity.add("bankCardNumber", bankcard);
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        resMap = JSONObject.fromObject(result);
        return resMap;
    }

    /**
     * 获取渠道费率
     * @param userId
     * @param amountMoney 提现金额
     * @return
     */
    public Map<String, Object> queryChannel(long userId, String amountMoney, String type) {
        /* 获取渠道费率 */
        RestTemplate restTemplate = new RestTemplate();
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri.toString() + "/v1.0/user/channel/queryDefaultChannelRate";
        MultiValueMap<String, Object> requsetEntitiy = new LinkedMultiValueMap<>();
        requsetEntitiy.add("userId", userId);
        requsetEntitiy.add("payType", "2");
        requsetEntitiy.add("channelId", "-1");
        requsetEntitiy.add("amountMoney", amountMoney);
        requsetEntitiy.add("type", type);
        String result = restTemplate.postForObject(url, requsetEntitiy, String.class);
        log.info("查询渠道费率/v1.0/user/channel/queryDefaultChannelRate result = " + result);

        Map<String, Object> res = new HashMap<>();

        JSONObject jsonObject = JSONObject.fromObject(result);
        JSONArray jsonArray = (JSONArray) jsonObject.get("result");
        for (int i = 0; i < jsonArray.size(); i++) {
            Map<String, Object> map = (Map<String, Object>) jsonArray.get(i);
            Set<String> set = map.keySet();
            if(set != null && !set.isEmpty()) {
                for(String key : set) {
                    if(map.get(key).equals(null)) {
                        map.put(key, "empty");
                    }
                }
            }
            String channelTag = map.get("channelTag").toString();
            if ("CHANPAYNEWCARD_0101".equals(channelTag)) {
                //选取费率最低的返回
                res.put("defaultChannel", map);
            }
        }
        return res;
    }

    /**
     * 交易回调
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/bindCardCallback")
    public String bindCardCallback(FreeQuickResponse response) {
        Map<String,String> data = response.getResultMap();
        String code = MapUtils.getString(data,"code");
        String requestNo = "";
        try {
            if (code.equals("200")) {
                String bizCode = MapUtils.getString(data,"bizCode");
                String status = MapUtils.getString(data,"status");
                requestNo = MapUtils.getString(data, "requestNo");
                FreeQuickOrder freeQuickOrder = freeQuickOrderRepository.findByRequestNo(requestNo);
                if (bizCode.equals("1")) {
                    if (status.toUpperCase().equals(OrderStatus.SUCCESS.getValue())) {
                        freeQuickOrder.setPayStatus("1");
                        freeQuickOrderRepository.save(freeQuickOrder);
                        return "SUCCESS";
                    }
                }
                freeQuickOrder.setPayStatus("3");
                freeQuickOrderRepository.save(freeQuickOrder);
            }
            return "SUCCESS";
        } catch (Exception e) {
            log.info("交易回调异常" + requestNo +"error {}" + e.getMessage());
            return "SUCCESS";
        }
    }

    /**
     * 提现回调
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/withdrawCallback")
    public String withdrawCallback(FreeQuickResponse response) {
        Map<String,String> data = response.getResultMap();
        String code = MapUtils.getString(data,"code");
        String requestNo = "";
        try {
            if (code.equals("200")) {
                String bizCode = MapUtils.getString(data,"bizCode");
                String status = MapUtils.getString(data,"status");
                requestNo = MapUtils.getString(data, "requestNo");
                FreeQuickWithdrawTemp freeQuickWithdrawTemp = freeQuickWithdrawTempRepository.findByRequestNo(requestNo);
                if (bizCode.equals("1")) {
                    if (status.toUpperCase().equals(OrderStatus.SUCCESS.getValue())) {
                        freeQuickWithdrawTemp.setPayStatus("1");
                        freeQuickWithdrawTempRepository.save(freeQuickWithdrawTemp);
                        return "SUCCESS";
                    }
                }
                freeQuickWithdrawTemp.setPayStatus("0");
                freeQuickWithdrawTempRepository.save(freeQuickWithdrawTemp);
            }
            return "SUCCESS";
        } catch (Exception e) {
            log.info("交易回调异常" + requestNo +"error {}" + e.getMessage());
            return "SUCCESS";
        }
    }

    /**
     * 获取当日分润收益
     * @param userId
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/getTodayIncome")
    public @ResponseBody Object getTodayIncome(@RequestParam(value = "userId") String userId) {
        BigDecimal todayIncome = freeQuickPayService.getTodayIncome(userId);
        return CommonsUtil.returnSuccess("查询成功", todayIncome);
    }


    /**
     * 分页查询充值记录
     * @param userId
     * @param page
     * @param size
     * @param direction
     * @param sortProperty
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/rechargePage")
    public @ResponseBody Object rechargePage(@RequestParam(value = "userId") String userId,
                                             @RequestParam(value = "status") String status,
                                             @RequestParam(value = "page", defaultValue = "0", required = false) int page,
                                             @RequestParam(value = "size", defaultValue = "20", required = false) int size,
                                             @RequestParam(value = "order", defaultValue = "DESC", required = false) Sort.Direction direction,
                                             @RequestParam(value = "sort", defaultValue = "createTime", required = false) String sortProperty) {
        if (StringUtils.isEmpty(userId)) {
            return CommonsUtil.returnError("无法查看！");
        }
        Pageable pageable = new PageRequest(page, size, new Sort(direction, sortProperty));
        try {
            Page<FreeQuickWithdraw> freeQuickWithdrawPage = freeQuickPayService.rechargePage(userId, status, pageable);
            List<FreeQuickWithdraw> content = freeQuickWithdrawPage.getContent();
            for (FreeQuickWithdraw free : content) {
                free.setChannelTag(free.ofChannelTag());
                FreeQuickWithdraw.emptyToString(free);
            }
            return CommonsUtil.returnSuccess("充值记录查询成功！", freeQuickWithdrawPage);
        } catch (Exception e) {
            return CommonsUtil.returnError("服务器异常，请稍后再试！");
        }
    }

    /**
     * 代还接口
     * @param freeQuickWithdraw
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/taskWithdraw")
    @ResponseBody
    public  Object taskWithdraw(FreeQuickWithdraw freeQuickWithdraw) {
        try {
            Map<String,Object> map = getMerchantNo(freeQuickWithdraw.getUserId(),freeQuickWithdraw.getChannelCode());
            if (map != null) {
                Map<String, String> result = MapUtils.getMap(map, "result");
                String merchantNo = result.getOrDefault("merchantNo", "0");
                if (merchantNo.equals("0")) {
                    return CommonsUtil.returnError("用户信息不完整");
                }
                freeQuickWithdraw.setMerchantNo(merchantNo);
                Map<String, String> pram = freeQuickPayService.taskWithdraw(freeQuickWithdraw);
                return pram;
            }
            return CommonsUtil.returnError("代还失败");
        }catch (Exception e){
            log.error("FreeQuickPayController.taskWithdraw,代还异常====="+e.getMessage());
            return CommonsUtil.returnError("代还失败！");
        }
    }

    /**
     * 代付提现查询接口：商户通过该接口可以从畅捷平台查询提现结果
     * @param token
     * @param merchantNo 开店管家商户编号
     * @param requestNo 请求流水号
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/queryWithDraw/{token}")
    public @ResponseBody Object queryWithDraw(@PathVariable String token,
                                              String merchantNo, String requestNo) {
        long sysUserId;
        try {
            sysUserId = TokenUtil.getUserId(token);
        } catch (Exception e) {
            return CommonsUtil.returnError("token无效！");
        }
        // 1、验证后台管理员身份
        try {
            long roleId = getUserRoleId(sysUserId);
            if (roleId != 1) {
                // 1为系统管理员
                return CommonsUtil.returnError("非系统管理员无法查询该商户提现信息！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return CommonsUtil.returnError("获取系统管理员角色信息失败！");
        }
        // 2、查询提现结果信息
        try {
            Map<String, Object> resMap = freeQuickPayService.queryWithDraw(merchantNo, requestNo);
            return CommonsUtil.returnSuccess("查询成功！", resMap);
        } catch (ServiceException e) {
            e.printStackTrace();
            return CommonsUtil.returnError(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return CommonsUtil.returnError("服务器异常，请稍后再试！");
        }
    }

    /**
     * 获取用户角色
     * @param userId id
     * @return
     * @throws ServiceException
     */
    private long getUserRoleId(long userId) throws ServiceException {
        URI user = util.getServiceUrl("user", "error url request!");
        String url = user + "/v1.0/user/userRole/queryUserRole";

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("userId", userId);

        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.postForObject(url, body, String.class);

        JSONObject jsonObject = JSONObject.fromObject(result);
        String respCode = jsonObject.getString(CommonConstants.RESP_CODE);
        if (!CommonConstants.SUCCESS.equals(respCode)) {
            String respMsg = jsonObject.getString(CommonConstants.RESP_MESSAGE);
            throw new ServiceException(respMsg);
        }
        jsonObject = jsonObject.getJSONObject(CommonConstants.RESULT);
        return jsonObject.getLong("roleId");
    }

    /**
     * 管理后台-分页查询无卡分润信息
     * @param phone
     * @param requestNo
     * @param channelTag
     * @param startTime
     * @param endTime
     * @param page
     * @param size
     * @param direction
     * @param sortProperty
     * @return
     */
    @GetMapping(value = "/v1.0/paymentchannel/freeQuickPay/noCardRebatePage")
    public @ResponseBody Object noCardRebatePage(@RequestParam(required = false) String phone,
                                                 @RequestParam(required = false) String requestNo,
                                                 @RequestParam(required = false) String channelTag,
                                                 @RequestParam(required = false) String startTime,
                                                 @RequestParam(required = false) String endTime,
                                                 @RequestParam(value = "page", defaultValue = "0", required = false) int page,
                                                 @RequestParam(value = "size", defaultValue = "20", required = false) int size,
                                                 @RequestParam(value = "order", defaultValue = "DESC", required = false) Sort.Direction direction,
                                                 @RequestParam(value = "sort", defaultValue = "createTime", required = false) String sortProperty) {
        Pageable pageable = new PageRequest(page, size, new Sort(direction,sortProperty));
        try {
            Map<String, Object> freeQuickOrderPage = freeQuickPayService.noCardRebatePage(phone, requestNo, channelTag, startTime, endTime, pageable);
            return CommonsUtil.returnSuccess("查询成功！", freeQuickOrderPage);
        } catch (ServiceException e) {
            e.printStackTrace();
            return CommonsUtil.returnError(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return CommonsUtil.returnError("服务器异常，请稍后再试！");
        }
    }

    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/query/syn")
    public @ResponseBody Object querySyn(@RequestParam(value = "sort", defaultValue = "requestNo")String requestNo) {
        FreeQuickOrder freeQuickOrder = freeQuickOrderRepository.findByRequestNo(requestNo);
        return CommonsUtil.returnOK(freeQuickOrder);
    }

    /**
     * 查询商户个人钱包
     */
    @RequestMapping(method = RequestMethod.POST, value = "/v1.0/paymentchannel/freeQuickPay/query/merch")
    public @ResponseBody Object queryMerct(@RequestParam(value = "phone") String phone) {
        Map<String,String> pram = freeQuickPayService.queryMerct(phone);
        return CommonsUtil.returnOK(pram);
    }


    /**
     * 畅捷提现/代还/下发
     */
    @RequestMapping(method= RequestMethod.POST,value="/v1.0/paymentchannel/freeQuick/repayment")
    public @ResponseBody Object repayment(FreeQuickWithdraw entity){
        try {
            entity.setXfSt("0");
            Map map = freeQuickPayService.withdraw(entity);
            String code = (String)map.getOrDefault("code","1");
            String msg = (String)map.getOrDefault("msg","1");
            if(code.equals("0")){
                return CommonsUtil.returnError(msg);
            }
            return CommonsUtil.returnSuccess("成功");
        }catch (Exception e){
            log.error("FreeQuickPayController.repayment畅捷提现/代还/下发接口异常======" + e.getMessage());
            return CommonsUtil.returnError("失败！" + e.getMessage());
        }
    }

    /**
     * APP-分页查询无卡分润信息
     * @param token
     * @param page
     * @param size
     * @param direction
     * @param sortProperty
     * @return
     */
    @ResponseBody
    @GetMapping(value = "/v1.0/paymentchannel/freeQuickPay/appClient/noCardRebatePage/{token}")
    public Object appNoCardRebatePage(@PathVariable String token,
                                      @RequestParam(value = "page", defaultValue = "0", required = false) int page,
                                      @RequestParam(value = "size", defaultValue = "20", required = false) int size,
                                      @RequestParam(value = "order", defaultValue = "DESC", required = false) Sort.Direction direction,
                                      @RequestParam(value = "sort", defaultValue = "createTime", required = false) String sortProperty) {
        long userId = TokenUtil.getUserId(token);
        if (userId == 0) {
            return CommonsUtil.returnError("token无效！");
        }
        try {
            Pageable pageable = new PageRequest(page, size, new Sort(direction,sortProperty));
            Map<String, Object> freeQuickOrderPage = freeQuickPayService.appNoCardRebatePage(userId, pageable);
            return CommonsUtil.returnSuccess("查询成功！", freeQuickOrderPage);
        } catch (ServiceException e) {
            e.printStackTrace();
            return CommonsUtil.returnError(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return CommonsUtil.returnError("服务器异常，请稍后再试！");
        }
    }
}
